﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Task = System.Threading.Tasks.Task;

namespace Agile.VSIX {

    /// <summary>
    /// This is the class that implements the package exposed by this assembly.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The minimum requirement for a class to be considered a valid package for Visual Studio is to
    /// implement the IVsPackage interface and register itself with the shell. This package uses the
    /// helper classes defined inside the Managed Package Framework (MPF) to do it: it derives from
    /// the Package class that provides the implementation of the IVsPackage interface and uses the
    /// registration attributes defined in the framework to register itself and its components with
    /// the shell. These attributes tell the pkgdef creation utility what data to put into .pkgdef file.
    /// </para>
    /// <para>
    /// To get loaded into VS, the package must be referred by &lt;Asset
    /// Type="Microsoft.VisualStudio.VsPackage" ...&gt; in .vsixmanifest file.
    /// </para>
    /// </remarks>
    [PackageRegistration(UseManagedResourcesOnly = true,AllowsBackgroundLoading = true)]
    [Guid(AgileVSIXPackage.PackageGuidString)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    [ProvideMenuResource("Menus.ctmenu",1)]
    public sealed class AgileVSIXPackage:AsyncPackage {

        /// <summary>
        /// Agile.VSIXPackage GUID string.
        /// </summary>
        public const string PackageGuidString = "5479ebdb-7817-4b7d-a672-9f2c2394c1e8";

        private DTE2 _ide;
        public DTE2 IDE => _ide ?? (_ide = (DTE2)GetService(typeof(DTE)));
        public double IDEVersion => Convert.ToDouble(IDE.Version,CultureInfo.InvariantCulture);

        public Document ActiveDocument {
            get {
                try {
                    return IDE.ActiveDocument;
                } catch(Exception) {
                    return null;
                }
            }
        }

        public AgileVSIXPackage() {
            Trace.WriteLine(string.Format(CultureInfo.CurrentCulture,"Entering constructor for: {0}",this));
        }

        #region Package Members

        /// <summary>
        /// Initialization of the package; this method is called right after the package is sited,
        /// so this is the place where you can put all the initialization code that rely on services
        /// provided by VisualStudio.
        /// </summary>
        /// <param name="cancellationToken">
        /// A cancellation token to monitor for initialization cancellation, which can occur when VS
        /// is shutting down.
        /// </param>
        /// <param name="progress">A provider for progress updates.</param>
        /// <returns>
        /// A task representing the async work of package initialization, or an already completed
        /// task if there is none. Do not return null from this method.
        /// </returns>
        protected override async Task InitializeAsync(CancellationToken cancellationToken,IProgress<ServiceProgressData> progress) {
            // When initialized asynchronously, the current thread may be a background thread at
            // this point. Do any initialization that requires the UI thread after switching to the
            // UI thread.
            await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            await Agile.VSIX.CodeSearchCommand.InitializeAsync(this);
            await Agile.VSIX.SortLinesCommand.InitializeAsync(this);
            await Agile.VSIX.JoinLinesCommand.InitializeAsync(this);
            await Agile.VSIX.CleanupActiveCodeCommand.InitializeAsync(this);
            await Agile.VSIX.CleanupAllCodeCommand.InitializeAsync(this);
            await Agile.VSIX.RemoveNullLineCommand.InitializeAsync(this);
        }

        #endregion Package Members
    }
}